﻿package ua.mihaylenko.vk 
{
	import caurina.transitions.Equations;
	import caurina.transitions.Tweener;
	import com.adobe.crypto.MD5;
	import com.adobe.serialization.json.JSON;
	import com.arkadium.socialru.vkapiclient.events.VKApiEvent;
	import com.arkadium.socialru.VKLogging;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.utils.Timer;
	import vk.gui.Box;
	/**
	 * ...
	 * @author Mihaylenko A.L.
	 */
	public class VKApi extends EventDispatcher
	{
		
		static private const IS_APP_USER:String = 'isAppUser';
		static private const GET_USER_SETTINGS:String = 'getUserSettings';
		static private const GET_UPLOAD_SERVER:String = 'photo.getPhotoUploadServer';
		static private const SAVE_TO_WALL:String = 'wall.savePost';
		static private const GET_FRIENDS_IDS:String = 'getFriends';
		static private const GET_APP_FRIENDS:String = 'getAppFriends';
		static private const GET_FRIENDS_INFO:String = 'getProfiles';
		static private const GET_WALL_POTS_UPLOAD_SERVER:String = 'wall.getPhotoUploadServer';
		static private var _VERSION:Number = 2.0;
		static private const TEST_MODE:String = '1';
		static private const SEND_NOTIFICATION:String = 'secure.sendNotification';
		static private const GET_UNIX_TIME:String = 'getServerTime';
		
		
		static private var $instance:VKApi;
		private var _cWrapper:Object;
		private var _iCurrentWidth:int = 0;
		private var _iCurrentHeight:int = 0;
		private var _iRequimentSettings:int;
		private var _iCurrentSettings:int;
		private var API_SEKRET:String;
		private var _sLan:String;
		private var _sURLResponse:String;
		private var _userId:uint;
		private var _appId:uint;
		private var _isAppUser:Boolean;
		private var _viewerId:uint;
		private var _sReffer:String;
		private var _sDomain:String;
		private var _cInfoBox:Box;
		private var _iDebug:int;
		private var _twWait:Timer;
		private var _bReffer:Boolean;
		public function VKApi() 
		{
			
		}
		
		static public function get instance():VKApi { if (!$instance)$instance = new VKApi(); return $instance; }
		/**
		 * Initialize wrapper, check app added 
		 * and check permitions
		 * @param	$wrapper - wrapper of applicatrion(root.parent.parent)
		 * @param	$requimentSettings - summ all permitions of this app ( VKApiSettings - class of constant all permitions)
		 * @param	$secret - api secret set when create app
		 */
		public function innit($wrapper:Object, $requimentSettings:int, $secret:String):void {
			_cWrapper = $wrapper;
			_iRequimentSettings = $requimentSettings;
			API_SEKRET = $secret;
			if (!_cWrapper) {
				_sURLResponse = "http://api.vkontakte.ru/api.php";
				_userId = 3044055;
				_appId = 1851304;
				_isAppUser = false;
				_viewerId = 3044055;
				_sReffer = '';
				_sDomain = "vkontakte.ru";
				_sLan = "en";
				dispatchEvent(new VKApiEvent(VKApiEvent.VK_INNIT_COMPLETE));
				return;				
			}
			if (_cWrapper.application.parameters.parent_language == 0) {
				_sLan = "ru";
			}else {
				_sLan = "en"
			}			
			_sURLResponse = _cWrapper.application.parameters.api_url;
			_userId = _cWrapper.application.parameters.user_id;
			_appId = _cWrapper.application.parameters.api_id;
			_iDebug = _cWrapper.application.parameters.debug;
			_isAppUser = Boolean(int(_cWrapper.application.parameters.is_app_user) == 1);
			_iCurrentSettings = _cWrapper.application.parameters.api_settings;
			_viewerId = _cWrapper.application.parameters.viewer_id;
			_sReffer = _cWrapper.application.parameters.referrer?_cWrapper.application.parameters.referrer:'';
			_sDomain = _cWrapper.application.parameters.domain;
			if(isRefer){
				_twWait = new Timer(1);
				_twWait.start();			
				checkAddedAndPermitions();
			}else {
				dispatchEvent(new VKApiEvent(VKApiEvent.SHOW_PRESENT));
			}
		}
		private function checkAddedAndPermitions():void {
			if(!_twWait){
				_twWait = new Timer(1000);
				_twWait.start();
			}
			if (!_isAppUser) {
				if(_sLan=='en'){
					_cInfoBox = new Box("Install", "To work correctly, add the application!", 0, 250, ['Install']);
				}else {
					_cInfoBox = new Box("Установка", "Для корректной работы добавьте приложение!", 0, 250, ['Добавить']);
				}
				_cInfoBox.x = (VKLogging.gameContainer.stage.stageWidth - _cInfoBox.width) / 2;
				_cInfoBox.y = (VKLogging.gameContainer.stage.stageHeight - _cInfoBox.height) / 2;
				_cInfoBox.visible = true;
				VKLogging.gameContainer.addChild(_cInfoBox);
				_cInfoBox.addEventListener(Event.SELECT, onShowAddApp);
			}else if (_iCurrentSettings < _iRequimentSettings || ((_iCurrentSettings - VKApiSettings.QUICK_MENU) >= 0 && (_iCurrentSettings - VKApiSettings.QUICK_MENU) < _iRequimentSettings)) {
				if (_sLan == 'en') {
					_cInfoBox = new Box("Settings", "To work correctly, should allow the application of the action!", 0, 250, ['Allow']);
				}else {
					_cInfoBox = new Box("Настройки", "Для корректной работы необходимо разрешить приложению действия!", 0, 250, ['Разрешить']);
				}
				_cInfoBox.x = (VKLogging.gameContainer.stage.stageWidth - _cInfoBox.width) / 2;
				_cInfoBox.y = (VKLogging.gameContainer.stage.stageHeight - _cInfoBox.height) / 2;
				_cInfoBox.visible = true;
				VKLogging.gameContainer.addChild(_cInfoBox);
				_cInfoBox.addEventListener(Event.SELECT, onShowPermitionBox);
			}else {
				_twWait.stop();
				_twWait = null;
				dispatchEvent(new VKApiEvent(VKApiEvent.VK_INNIT_COMPLETE));
			}
		}
		
		private function onIshureAdded(e:Event):void 
		{
			_cWrapper.removeEventListener(VKApiEvent.WINDOW_FOCUS, onIshureAdded);
			
			var cURLoader:URLLoader = new URLLoader();
			cURLoader.addEventListener(Event.COMPLETE, checkAdded);
			cURLoader.load(generate_request(IS_APP_USER));			
		}
		
		private function checkAdded(e:Event):void 
		{
			var cURLoader:URLLoader = e.currentTarget as URLLoader;
			cURLoader.removeEventListener(Event.COMPLETE, checkAdded);
			_isAppUser = Boolean(int(JSON.decode(cURLoader.data).response) == 1);
			if (_isAppUser) {
				_twWait = new Timer(1);
				_twWait.start();
			}
			checkAddedAndPermitions();
		}		
		
		
		private function onShowAddApp(e:Event):void {
			_cInfoBox.visible = true;
			if (!_twWait) return;
			if (_twWait.currentCount < 2) return;
			_twWait.stop();
			_twWait = null;
			_cWrapper.external.showInstallBox();
			if (_cInfoBox) {
				_cInfoBox.removeEventListener(Event.SELECT, onShowAddApp);
				if (VKLogging.gameContainer.contains(_cInfoBox)) VKLogging.gameContainer.removeChild(_cInfoBox);
				_cInfoBox = null;
			}
			_cWrapper.addEventListener(VKApiEvent.WINDOW_FOCUS, onIshureAdded);			
		}
		
		private function onShowPermitionBox(e:Event):void 
		{
			_cInfoBox.visible = true;
			if (!_twWait) return;
			if (_twWait.currentCount < 2) return;
			_twWait.stop();
			_twWait = null;
			_cWrapper.external.showSettingsBox(_iRequimentSettings + VKApiSettings.QUICK_MENU);
			if (_cInfoBox) {
				_cInfoBox.removeEventListener(Event.SELECT, onShowPermitionBox);
				if (VKLogging.gameContainer.contains(_cInfoBox)) VKLogging.gameContainer.removeChild(_cInfoBox);
				_cInfoBox = null;
			}
			_cWrapper.addEventListener(VKApiEvent.WINDOW_FOCUS, onIshureSettings);
			
		}
		private function onIshureSettings(e:Event):void 
		{
			_cWrapper.removeEventListener(VKApiEvent.WINDOW_FOCUS, onIshureSettings);
			var cURLoader:URLLoader = new URLLoader();
			cURLoader.addEventListener(Event.COMPLETE, checkSettings);
			cURLoader.load(generate_request(GET_USER_SETTINGS));
		}
		private function checkSettings(e:Event):void {
			var cURLoader:URLLoader = e.currentTarget as URLLoader;
			cURLoader.removeEventListener(Event.COMPLETE, checkAdded);
			_iCurrentSettings = JSON.decode(cURLoader.data).response.settings;
			checkAddedAndPermitions();
		}
		/**
		 * Generate request for VK api
		 * @param	method
		 * @param	params
		 * @return
		 */
		private function generate_request(method:String, params:Object = null):URLRequest {
			var request_params: Object = {method: method};
			request_params.api_id = _appId;
			request_params.format = "JSON";
			request_params.test_mode = TEST_MODE;
			if(params){
				for (var i: String in params) {
				  request_params[i] = params[i];
				}
			}
			var variables:URLVariables = new URLVariables();
			for (var j: String in request_params) {
				variables[j] = request_params[j];
			}
			variables['sig'] = generate_signature(request_params);

			var request:URLRequest = new URLRequest();
			request.url = _sURLResponse;
			request.method = URLRequestMethod.POST;
			request.data = variables;
			return request;
		}
		/**
		 * Generates signature
		 *
		 */
		private function generate_signature(request_params: Object): String {
		  var signature: String = "";
		  var sorted_array: Array = new Array();
		  for (var key: String in request_params) {
			sorted_array.push(key + "=" + request_params[key]);
		  }
		  sorted_array.sort();

		  // Note: make sure that the signature parameter is not already included in
		  //       request_params array.
		  for (key in sorted_array) {
			signature += sorted_array[key];
		  }
				if (_viewerId > 0) signature = _viewerId.toString() + signature;
		  signature += API_SEKRET;
		  return MD5.hash(signature);
		}		
		/**
		 * resize VK display object wrapper
		 * @param	iWidth - num of width of wrapper (default 150 px)
		 * @param	iHeight - num of height of wrapper (default 100 px)
		 * @param	$time - time of resize (default 15 frames)
		 */
		public function resize(iWidth:int = 150, iHeight:int = 100, $time:int = 100 ):void {
			if (!_cWrapper) return;
			//Tweener.addTween(this, { width:iWidth, height:iHeight, time:$time, useFrames:true, transition:Equations.easeOutQuint } );
			
		}
		public function set width(iValue:int):void {
			_iCurrentWidth = iValue;
			_cWrapper.external.resizeWindow(_iCurrentWidth, _iCurrentHeight);
		}
		public function set height(iValue:int):void {
			_iCurrentHeight = iValue;
			_cWrapper.external.resizeWindow(_iCurrentWidth, _iCurrentHeight);
		}
		public function get width():int { return _iCurrentWidth; }
		public function get height():int { return _iCurrentHeight; }
		//////////////////////////////////////////////////////
		/**
		 * get current vk lang this is parameters 
		 * from wrapper(set when load wrapper) when change lan 
		 * then reload wrapper and game
		 */
		public function get language():String { return _sLan; }
		public function get isRefer():Boolean { 
			return Boolean(_sReffer == '' || _sReffer == 'menu' || _sReffer == 'wall_post_inline' || _sReffer == 'wall_view'); 
		}
	}

}